/**
  ******************************************************************************
  * @文件名           : dri_slaver_smc_ascii.c
  * @作者             : citunhk
  * @功能介绍         : SMC_ASCII从机驱动
  *	@日期             : 2024.3.6
  ******************************************************************************
  * @注意
  *
  * 本文件中不应调用上层文件
  *
  ******************************************************************************
  *更改记录
  *日期 修改人 修改内容
  *
  *
  *
  ******************************************************************************
  */
#include "dri_slaver_smc_ascii.h"
#include "dri_slaver.h"
#include "bsp_usart.h"
#include "fml_lrc.h"
#include "sys_data.h"
#include "dri_flash_sst.h"

uint8_t gBus485_Hex_RxBuffer[RS485_SELVER_RX_NUM];  //HEX接收数组
uint8_t gBus485_Merge_RxBuffer[RS485_SELVER_RX_NUM];  //接收合并数组

uint8_t gBus485_Data_TxBuffer[RS485_SELVER_TX_NUM];  //待发送数据数组
uint8_t gBus485_Split_TxBuffer[RS485_SELVER_TX_NUM];  //发送拆分数组

uint16_t gBus485_Data_TxCounter = 0;  //待发送数据字节数

/**
* @函数名	DRI_Slaver_Ascii_Hex
* @功能	    将从机接收数组的Ascii转换为Hex格式
* @入口参数	table_ascii  待转换数组
* 			addr_ascii	转换首地址
* 			num		转换字节数
* 			table_hex  转换输出数组
* 			addr_hex	转换输出数组首地址
* @返回值	无
*/
void DRI_Slaver_Ascii_Hex(uint8_t table_ascii[],uint16_t addr_ascii,uint16_t num,uint8_t table_hex[],uint8_t addr_hex)
{
	uint16_t i = addr_ascii;
	uint16_t j = addr_hex;

	for(i=addr_ascii;i<num;i++)
	{
		if((table_ascii[i] >= '0') && (table_ascii[i] <= '9'))
		{
			table_hex[j++] = table_ascii[i] - '0';
		}
		else if((table_ascii[i] >= 'A') && (table_ascii[i] <= 'F'))
		{
			table_hex[j++] = table_ascii[i] - 'A' + 0x0A;
		}
		else if((table_ascii[i] >= 'a') && (table_ascii[i] <= 'f'))
		{
			table_hex[j++] = table_ascii[i] - 'a' + 0x0A;
		}
//		else
//		{
//
//		}
	}
}

/**
* @函数名	DRI_Slaver_Hex_Ascii
* @功能	    将从机发送数组的Hex转换为Ascii格式
* @入口参数	table_hex  待转换数组
* 			addr_hex    转换首地址
* 			num		转换字节数
* 			table_ascii  转换输出数组
* 			addr_ascii  转换输出数组首地址
* @返回值	无
*/
void DRI_Slaver_Hex_Ascii(uint8_t table_hex[],uint16_t addr_hex,uint16_t num,uint8_t table_ascii[],uint16_t addr_ascii)
{
	uint16_t i = addr_hex;
	uint16_t j = addr_ascii;

	for(i=addr_hex;i<num;i++)
	{
		if((table_hex[i] >= 0) && (table_hex[i] <= 9))
		{
			table_ascii[j++] = table_hex[i] + '0';
		}
		else if((table_hex[i] >= 10) && (table_hex[i] <= 16))
		{
			table_ascii[j++] = table_hex[i] + 'A' - 0x0A;
		}
//		else
//		{
//
//		}
	}
}

/**
* @函数名	DRI_Merge
* @功能	    合并相邻字节
* @入口参数	gTable1  待合并数组
* 			addr1	 待合并地址
* 			num		 待合并字节数
* 			gTable2  合并后输出数组
* 			addr2    合并后输出数组起始地址
* @返回值	合并是否正确值
*/
uint8_t DRI_Merge(uint8_t gTable1[],uint16_t addr1,uint16_t num,uint8_t gTable2[],uint16_t addr2)
{
	uint16_t i = addr1;
	uint16_t j = addr2;

	if(num%2 == 0)
	{
		for(i=addr1;i<num;i+=2)
		{
			gTable2[j] = (gTable1[i]<<4) + (gTable1[i+1] & 0x0F);
			j++;
		}
		return 1;
	}
	else
	{
		return 0;
	}
}

/**
* @函数名	DRI_Split
* @功能	    拆分字节
* @入口参数	gTable1  待拆分数组
* 			addr1	 待拆分地址
* 			num		 待拆分字节数
* 			gTable2  拆分后输出数组
* 			addr2	 拆分后输出数组起始地址
* @返回值	合并是否正确值
*/
void DRI_Split(uint8_t gTable1[],uint16_t addr1,uint16_t num,uint8_t gTable2[],uint16_t addr2)
{
	uint16_t i = addr1;
	uint16_t j = addr2;

	for(i=addr1;i<num;i++)
	{
		gTable2[j++] = (gTable1[i]&0xf0)>>4;
		gTable2[j++] = gTable1[i]&0x0f;
	}
}

/**
* @函数名	DRI_SMC_ASCII_TxRegSlaverValue
* @功能	    将23指令需要的数据填充到相应的寄存器中
* @入口参数	无
* @返回值	无
*/
void DRI_SMC_ASCII_TxRegSlaverValue(void)
{
	uint32_t pReadStart;
	uint32_t pReadQuantity;
	uint32_t pReadEnd;
	uint16_t i;
	uint16_t pModbusSlaverUpData = 0;

	//读取起始地址
	pReadStart = ((uint16_t)gBus485_Merge_RxBuffer[2]<<8)+gBus485_Merge_RxBuffer[3];
	//读取寄存器个数
	pReadQuantity = ((uint16_t)gBus485_Merge_RxBuffer[4]<<8)+gBus485_Merge_RxBuffer[5];
	//读取结束地址
	pReadEnd = pReadStart + pReadQuantity;

	if(pReadQuantity > 0x7D)  //读的数量超出范围
	{
		gErr_Code_SMC = 3;
		return;
	}

	if(pReadStart > 0x0F)  //读取起始地址超范围
	{
		gErr_Code_SMC = 2;
		return;
	}

	if(pReadEnd > 0x10)  //读取结束地址超范围
	{
		gErr_Code_SMC = 2;
		return;
	}

	//装填读取字节数
	gBus485_Data_TxBuffer[gBus485_Data_TxCounter++] = pReadQuantity*2;

	for(i=pReadStart;i<pReadEnd;i++)
	{
		switch(i)
		{
		case 0:
			pModbusSlaverUpData = ((int16_t)(10*gPV_Temp1));//主温度实测值
			break;
		case 1:
			pModbusSlaverUpData = 10*gPV_Flow;//流量实测值
			break;
		case 2:
			pModbusSlaverUpData = 10*gPV_Press_Out;//出液压力实测值
			break;
		case 3:
			pModbusSlaverUpData = 0;  //循环液电导率  暂不支持
			break;
		case 4:
			pModbusSlaverUpData = rSlaver_State_Chiller1;  //状态字1
			break;
		case 5:
			pModbusSlaverUpData = rSlaver_State_Alarm1;  //报警字1
			break;
		case 6:
			pModbusSlaverUpData = rSlaver_State_Alarm2;  //报警字2
			break;
		case 7:
			pModbusSlaverUpData = 0;  //保留
			break;
		case 8:
			pModbusSlaverUpData = 0;  //保留
			break;
		case 9:
			pModbusSlaverUpData = 0;  //保留
			break;
		case 10:
			pModbusSlaverUpData = 0;  //保留
			break;
		case 11:
			pModbusSlaverUpData=((int16_t)(10*UP.Para.SV_Temp1));//主温度设定值
			break;
		case 12:
			pModbusSlaverUpData = rSlaver_State_Control1 & 0x03;  //控制字
			break;
		case 13:
			pModbusSlaverUpData = UP.Para.SV_Flow;  //流量设定值
			break;
		case 14:
			pModbusSlaverUpData = 0;  //保留
			break;
		case 15:
			pModbusSlaverUpData = 0;  //保留
			break;
			default:
	//			gSlaver_State = 50;
			break;
		}

		gBus485_Data_TxBuffer[gBus485_Data_TxCounter++]=(uint8_t)(pModbusSlaverUpData>>8);
		gBus485_Data_TxBuffer[gBus485_Data_TxCounter++]=(uint8_t)pModbusSlaverUpData;
	}
}

/**
* @函数名	DRI_WriteRegSlaverValue_SMC
* @功能	    将23指令接收的数据填充到相应的寄存器中
* @入口参数	无
* @返回值	无
*/
void DRI_SMC_ASCII_WriteRegSlaverValue(void)
{
	uint32_t pWriteStart;
	uint32_t pWriteRegQuantity;
	uint32_t pWriteByteQuantity;
	uint32_t pWriteEnd;
	uint16_t FlagCmdModbus = 0;
	uint8_t pFlag_Save = 1;  //保存标志位
	uint16_t i;
	float pSV_Temp = 0;

	//写入起始地址
	pWriteStart = ((uint16_t)gBus485_Merge_RxBuffer[6]<<8) + gBus485_Merge_RxBuffer[7];
	//写入寄存器个数
	pWriteRegQuantity = ((uint16_t)gBus485_Merge_RxBuffer[8]<<8) + gBus485_Merge_RxBuffer[9];
	//写入字节个数
	pWriteByteQuantity = gBus485_Merge_RxBuffer[10];
	//写入结束地址
	pWriteEnd = pWriteStart + pWriteRegQuantity;

	if(pWriteRegQuantity == 0)  //没有写入
	{
		return;
	}
	else if(pWriteRegQuantity > 0x79)  //写寄存器数量超范围
	{
		gErr_Code_SMC = 3;
		return;
	}

	//接收数组有问题
	if(pWriteByteQuantity != (pWriteRegQuantity*2))
	{
		gErr_Code_SMC = 3;
		return;
	}

	if((pWriteStart < 0x0B) || (pWriteStart > 0x0F))  //写入起始地址超范围
	{
		gErr_Code_SMC = 2;
		return;
	}

	if(pWriteEnd > 0x10)  //写结束超范围
	{
		gErr_Code_SMC = 2;
		return;
	}

	for(i=pWriteStart;i<pWriteEnd;i++)
	{
		switch(i)
		{
			case 11:  //主温度设定值
				pSV_Temp = ((float)(int16_t)((uint16_t)(gBus485_Merge_RxBuffer[11+FlagCmdModbus]<<8) + gBus485_Merge_RxBuffer[12+FlagCmdModbus]))/10;

				if(pSV_Temp < FP.Para.LL_TempSV1)  //设置目标温度超过下限值
				{
					UP.Para.SV_Temp1 = FP.Para.LL_TempSV1;
				}
				else if(pSV_Temp > FP.Para.HL_TempSV1)  //设置目标温度超过上限值
				{
					UP.Para.SV_Temp1 = FP.Para.HL_TempSV1;
				}
				else
				{
					UP.Para.SV_Temp1 = pSV_Temp;
				}

				FlagCmdModbus = FlagCmdModbus + 2;
				break;
			case 12:  //控制字1
				rSlaver_State_Control1 = (uint16_t)(gBus485_Merge_RxBuffer[11+FlagCmdModbus]<<8) + gBus485_Merge_RxBuffer[12+FlagCmdModbus];
				FlagCmdModbus = FlagCmdModbus + 2;
				pFlag_Save = 0;
				break;
			case 13:  //流量设定值
				UP.Para.SV_Flow = (uint16_t)(gBus485_Merge_RxBuffer[11+FlagCmdModbus]<<8) + gBus485_Merge_RxBuffer[12+FlagCmdModbus];
				FlagCmdModbus = FlagCmdModbus + 2;
				break;
			default:
				break;
		}
	}

	if(pFlag_Save == 1)
	{
		DRI_Flash_Erase_4KByte(ADDR_USER_PARA);//写入前擦除
		DRI_Flash_AAI_WriteBuffer(&UP.flashBuff[0], ADDR_USER_PARA, 500);//写入用户初值到buff中
	}
}

/**
* @函数名	DRI_SMC_ASCII_ProcessModbusSlaverUpCmd23
* @功能	    23指令解析处理
* @入口参数	无
* @返回值	无
*/
void DRI_SMC_ASCII_ProcessModbusSlaverUpCmd23(void)
{
	uint8_t pLrcData;

	//返回数据装填
	gBus485_Data_TxCounter = 0;
	gBus485_Data_TxBuffer[gBus485_Data_TxCounter++] = gBus485_Merge_RxBuffer[0];  //地址
	gBus485_Data_TxBuffer[gBus485_Data_TxCounter++] = gBus485_Merge_RxBuffer[1];  //功能码

	//字节个数与读取数据返回
	DRI_SMC_ASCII_TxRegSlaverValue();

	if(gErr_Code_SMC == 0)  //读取正常
	{
		//LRC校验
		pLrcData = LRC(gBus485_Data_TxBuffer,gBus485_Data_TxCounter);
		gBus485_Data_TxBuffer[gBus485_Data_TxCounter++] = pLrcData;

		//拆分数据
		DRI_Split(gBus485_Data_TxBuffer,0,gBus485_Data_TxCounter,gBus485_Split_TxBuffer,0);

		//转换数据
		DRI_Slaver_Hex_Ascii(gBus485_Split_TxBuffer,0,(2*gBus485_Data_TxCounter),pBus485_Slaver_TxBuffer,1);


		//结束符
		pBus485_Slaver_TxCounter = 2*gBus485_Data_TxCounter + 1;
		pBus485_Slaver_TxBuffer[0] = ':';
		pBus485_Slaver_TxBuffer[pBus485_Slaver_TxCounter++] = '\r';
		pBus485_Slaver_TxBuffer[pBus485_Slaver_TxCounter++] = '\n';

		//写入数据
		DRI_SMC_ASCII_WriteRegSlaverValue();

		if(gErr_Code_SMC == 0)  //写入正常
		{
			//返回数据
			DRI_SlaverUpStartTx();
		}
		else  //写入异常
		{
			return;
		}
	}
	else  //读取异常
	{
		return;
	}
}

/**
* @函数名	DRI_SMC_ASCII_Err
* @功能	    通讯错误处理
* @入口参数	errsmccode  错误代码
* @返回值	无
*/
void DRI_SMC_ASCII_Err(uint8_t errsmccode)
{
	uint8_t pLrcData;

	//返回数据装填
	gBus485_Data_TxCounter = 0;
	gBus485_Data_TxBuffer[gBus485_Data_TxCounter++] = gBus485_Merge_RxBuffer[0];
	gBus485_Data_TxBuffer[gBus485_Data_TxCounter++] = gBus485_Merge_RxBuffer[1] + 0x80;  //请求消息功能码 + 0x80
	gBus485_Data_TxBuffer[gBus485_Data_TxCounter++] = gErr_Code_SMC;  //错误代码

	//LRC校验
	pLrcData = LRC(gBus485_Data_TxBuffer,gBus485_Data_TxCounter);
	gBus485_Data_TxBuffer[gBus485_Data_TxCounter++] = pLrcData;

	//拆分数据
	DRI_Split(gBus485_Data_TxBuffer,0,gBus485_Data_TxCounter,gBus485_Split_TxBuffer,0);

	//转换数据
	DRI_Slaver_Hex_Ascii(gBus485_Split_TxBuffer,0,(2*gBus485_Data_TxCounter),pBus485_Slaver_TxBuffer,1);

	//结束符
	pBus485_Slaver_TxCounter = 2*gBus485_Data_TxCounter + 1;
	pBus485_Slaver_TxBuffer[0] = ':';
	pBus485_Slaver_TxBuffer[pBus485_Slaver_TxCounter++] = '\r';
	pBus485_Slaver_TxBuffer[pBus485_Slaver_TxCounter++] = '\n';

	//返回数据
	DRI_SlaverUpStartTx();
}

/**
* @函数名	DRI_SMC_ASCII_Slaver_RX_Integration
* @功能	    SMC_ASCII的RS485从机数据处理
* @入口参数	无
* @返回值	无
*/
void DRI_SMC_ASCII_Slaver_RX_Integration(void)
{
	uint8_t puiLRCResult;
	uint8_t lrcdata;
	uint8_t pModbusUpFrameSlaverStatus=1;
	uint16_t i;

	if(gBus485_Slaver_RxCounter<3) //如果数据字节少于3
	{
		pModbusUpFrameSlaverStatus=1;
		gBus485_Slaver_RxCounter = 0;  //清除计数标志
	}
	else
	{
		//去除检验位
		for(i=0;i<gBus485_Slaver_RxCounter;i++)
		{
			gBus485_Slaver_RxBuffer[i] = gBus485_Slaver_RxBuffer[i] & 0x7F;
		}

		//起始符  结束符
		if((gBus485_Slaver_RxBuffer[0] == ':') && (gBus485_Slaver_RxBuffer[gBus485_Slaver_RxCounter-2] == '\r') && (gBus485_Slaver_RxBuffer[gBus485_Slaver_RxCounter-1] == '\n'))
		{
			//ASCII  变为  HEX
			DRI_Slaver_Ascii_Hex(gBus485_Slaver_RxBuffer,1,(gBus485_Slaver_RxCounter-2),gBus485_Hex_RxBuffer,0);

			pModbusUpFrameSlaverStatus=0;//接收成功
		}
		else
		{
			gBus485_Slaver_RxCounter = 0;  //清除计数标志
			pModbusUpFrameSlaverStatus=1;//接收失败
		}

		if(pModbusUpFrameSlaverStatus == 0)
		{
			//合并数组
			DRI_Merge(gBus485_Hex_RxBuffer,0,(gBus485_Slaver_RxCounter-3),gBus485_Merge_RxBuffer,0);

			puiLRCResult = LRC(gBus485_Merge_RxBuffer,((gBus485_Slaver_RxCounter-5)/2));  //计算LRC数值
			lrcdata = gBus485_Merge_RxBuffer[((gBus485_Slaver_RxCounter-3)/2-1)];  //获取LRC数值
			gBus485_Slaver_RxCounter = 0;  //清除计数标志
			if((lrcdata - puiLRCResult) == 0)//LRC校验通过
			{
				if(UP.Para.RS485_Addr == gBus485_Merge_RxBuffer[0])  //从机地址
				{
					pModbusUpFrameSlaverStatus=0;  //接收成功
					gSlaver_State = 0;
				}
				else
				{
					pModbusUpFrameSlaverStatus=1;//接收失败
					return;  //接收地址不一致，不做任何处理，直接返回
				}
			}
			else
			{
					pModbusUpFrameSlaverStatus=1;//接收失败
					return;  //LRC校验不正确，不做任何处理，直接返回
			}
		}
	}

	if(pModbusUpFrameSlaverStatus == 0)
	{
		if(gBus485_Merge_RxBuffer[0])  //地址不为0
		{
			switch(gBus485_Merge_RxBuffer[1])  //判断指令
			{
				case 23://读/写多个寄存器
					DRI_SMC_ASCII_ProcessModbusSlaverUpCmd23();
					break;
				default:
					gErr_Code_SMC = 1;
				break;
			}
		}
	}

	//错误处理
	if(gErr_Code_SMC != 0)
	{
		DRI_SMC_ASCII_Err(gErr_Code_SMC);  //发送错误代码
		gErr_Code_SMC = 0;
	}
}








